<template>
  <div class="poly-manager">
    <a-space style="display: flex; justify-content: flex-start; align-items: center; flex-wrap: nowrap">
      <a-button v-if="!isEditing && !isDrawing" type="primary" @click="draw">绘制</a-button>
      <a-button v-if="!isEditing && !!isDrawing" danger :type="'primary'" @click="draw(true)">结束</a-button>
      <a-button v-if="polyCounts" :disabled="isDrawing || isEditing" type="primary" @click="clear(), draw()">
        重绘
      </a-button>
      <a-button v-if="polyCounts" :disabled="isDrawing || isEditing" danger type="primary" @click="clear">
        清除
      </a-button>
      <!--      <a-button v-if="polyCounts && !isDrawing && !isEditing" type="primary" @click="modify">编辑</a-button>-->
      <!--      <a-button v-if="polyCounts && !isDrawing && !!isEditing" danger type="primary" @click="modify(true)">-->
      <!--        结束-->
      <!--      </a-button>-->
      <!--      <a-button :loading="loading" :type="isOtherPolyShow ? 'default' : 'primary'" @click="showAll">{{-->
      <!--        `${isOtherPolyShow ? '隐藏' : '显示'}上级和同级`-->
      <!--      }}</a-button>-->
    </a-space>
  </div>
</template>

<script>
import { DrawScene, PolygonDraw, PolygonEdit } from 'bmap-draw';
import { computed, inject, onMounted, onUnmounted, ref, watch } from 'vue';
import { isEqual } from 'lodash-es';
import { getLngLat } from './mapUtils.js';

const defaultPolyOption = {
  fillOpacity: 0.2,
  fillColor: '#3aa1fa',
  strokeOpacity: 0.8,
  strokeColor: '#3aa1fa',
};

export default {
  name: 'CMapPolyManager',
  components: {},
  emits: ['update:modelValue', 'change', 'status'],
  props: {
    modelValue: { type: Object, default: undefined },
    color: { type: String, default: undefined },
    useString: { type: Boolean, default: true },
    previewOnly: { type: Boolean, default: false }, // 预览模式
  },
  setup(props, { emit }) {
    let useMap = inject('useMap');
    let map = useMap();
    let scene = ref(new DrawScene(map, { noLimit: true }));
    let polygonDraw = ref(
      new PolygonDraw(scene.value, {
        isOpen: false,
        isSeries: true,
        baseOpts: { ...defaultPolyOption },
      })
    );
    let polygonEdit = ref(
      new PolygonEdit(scene.value, {
        isOpen: false,
        isSeries: true,
        baseOpts: { ...defaultPolyOption },
      })
    );
    let isDrawing = computed(() => !!polygonDraw.value.isOpen);
    let isEditing = computed(() => !!polygonEdit.value.isOpen);
    let polyCounts = computed(() => scene.value.instances.length);

    let polyValues = null;

    let clear = () => {
      scene.value.clearData();
      output();
    };

    let draw = (isEnd) => {
      if (isEnd === true) {
        polygonDraw.value.close();
        output();
        return;
      }
      isDrawing.value ? polygonDraw.value.close() : polygonDraw.value.open();
    };
    let modify = (isEnd) => {
      if (isEnd === true) {
        polygonEdit.value.close();
        output();
        return;
      }
      if (isEditing.value) {
        polygonEdit.value.close();
      } else {
        let poly = createPoly(polyValues);
        if (poly) {
          polygonEdit.value.open(poly);
        } else {
        }
      }
    };
    let parsePolyValues = (values) => {
      if (Array.isArray(values)) {
        return values.reduce((res, item) => {
          getLngLat(item, ([lng, lat]) => res.push([lng, lat]));
          return res;
        }, []);
      }
    };
    let createPoly = (values, next) => {
      if (values && values.length) {
        values = parsePolyValues(values);
        let path = values.map(([lng, lat]) => new BMap.Point(lng, lat));
        let poly = new BMap.Polygon(path, defaultPolyOption);
        typeof next === 'function' && next(poly);
        return poly;
      }
    };
    let output = () => {
      polyValues = scene.value.instances.reduce((res, item) => {
        let path = item.getPath().map(({ lng, lat }) => [lng, lat]);
        return res.concat(path);
      }, []);
      if (props.useString === true) {
        polyValues = polyValues.reduce((res, item) => {
          return res.concat(item.join(','));
        }, []);
        polyValues = polyValues.join(';');
      }
      emit('update:modelValue', polyValues);
      emit('change', polyValues);
    };

    watch(
      () => props.modelValue,
      (value) => {
        if (isEqual(value, polyValues)) return;
        if (props.useString === true) {
          if (typeof value !== 'string') return;
          value = value.split(';');
        }
        value = parsePolyValues(value);
        createPoly(value, (poly) => {
          map.addOverlay(poly);
          scene.value.addOverlay(poly);
        });
        polyValues = value;
      },
      { immediate: true, deep: false }
    );

    watch(
      () => props.color,
      (color) => {
        // debugger;
        if (color) {
          polygonDraw.value.baseOptions.fillColor = color;
          polygonDraw.value.baseOptions.strokeColor = color;
          polygonEdit.value.baseOptions.fillColor = color;
          polygonEdit.value.baseOptions.strokeColor = color;
          scene.value.instances.forEach((item) => {
            item.setStrokeColor(color);
            item.setFillColor(color);
          });
        }
      },
      { immediate: true }
    );

    onMounted(() => {
      watch(
        () => [isDrawing.value, isEditing.value],
        ([drawing, editing]) => {
          emit('status', drawing ? 'drawing' : editing ? 'editing' : 'none');
        },
        { immediate: true }
      );
    });

    onUnmounted(() => {
      polygonDraw.value.close();
      polygonEdit.value.close();
      polygonDraw = polygonEdit = null;
      props = emit = useMap = map = scene = isDrawing = isEditing = polyCounts = polyValues = null;
    });

    return { clear, draw, modify, polyCounts, isDrawing, isEditing };
  },
};
</script>

<style scoped></style>
